﻿namespace GreenIsomer.Web.Controls.JQuery {
	using System;
	using System.Web.UI;
	using System.ComponentModel;
	using System.Diagnostics.CodeAnalysis;

	/// <summary>
	/// Base server control used to generate the core functionality of a jQuery UI Slider widget.
	/// </summary>
	public abstract class SliderBase : JQueryWebControl {


		#region Constants: Property defaults

		private const bool defaultAnimate = false;
		private const int defaultMax = 100;
		private const int defaultMin = 0;
		private const Orientation defaultOrientation = Orientation.Auto;
		private const int defaultStep = 1;

		#endregion


		#region Constructors

		/// <summary>
		/// Initializes a new instance of the GreenIsomer.Web.Controls.JQuery.SliderBase class.
		/// </summary>
		protected SliderBase() : base(HtmlTextWriterTag.Div) { }

		#endregion


		#region Properties: Widget initialization options

		/// <summary>
		/// Whether to slide handle smoothly when user clicks outside handle on the bar.
		/// This property maps directly to the "animate" option when the jQuery UI widget is initialized.
		/// </summary>
		[DefaultValue(defaultAnimate), Category("Behavior")]
		public virtual bool Animate {
			get { return ViewState.GetValue("Animate", defaultAnimate); }
			set { ViewState["Animate"] = value; }
		}

		/// <summary>
		/// The maximum value of the slider.
		/// This property maps directly to the "max" option when the jQuery UI widget is initialized.
		/// </summary>
		[DefaultValue(defaultMax), Category("Behavior")]
		public virtual int Max {
			get { return ViewState.GetValue("Max", defaultMax); }
			set { ViewState["Max"] = value; }
		}

		/// <summary>
		/// The minimum value of the slider.
		/// This property maps directly to the "min" option when the jQuery UI widget is initialized.
		/// </summary>
		[DefaultValue(defaultMin), Category("Behavior")]
		public virtual int Min {
			get { return ViewState.GetValue("Min", defaultMin); }
			set { ViewState["Min"] = value; }
		}

		/// <summary>
		/// Normally you don't need to set this property because the plugin detects the slider orientation automatically. If the orientation is not correctly detected, you can set this property to "Horizontal" or "Vertical".
		/// This property maps directly to the "orientation" option when the jQuery UI widget is initialized.
		/// </summary>
		[DefaultValue(defaultOrientation), Category("Appearance")]
		public virtual Orientation Orientation {
			get { return ViewState.GetValue("Orientation", defaultOrientation); }
			set {
				if(!Enum.IsDefined(typeof(Orientation), value)) throw new ArgumentException("Value not defined.", "value");
				ViewState["Orientation"] = value;
			}
		}

		/// <summary>
		/// Determines the size or amount of each interval or step the slider takes between Min and Max. The full specified value range of the slider (Max - Min) needs to be evenly divisible by the step.
		/// This property maps directly to the "step" option when the jQuery UI widget is initialized.
		/// </summary>
		[DefaultValue(defaultStep), Category("Behavior")]
		[SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Step", Justification = "Exposed as the jQuery option name.")]
		public virtual int Step {
			get { return ViewState.GetValue("Step", defaultStep); }
			set { ViewState["Step"] = value; }
		}

		#endregion


		#region Events

		/// <summary>
		/// Occurs on postback when the Value property value has changed since previous render.
		/// </summary>
		[Category("Action")]
		public event EventHandler ValueChanged;

		#endregion


		#region Methods: Event hooks

		/// <summary>
		/// Raises the ValueChanged event.
		/// </summary>
		/// <param name="e">The System.EventArgs object that contains the event data.</param>
		protected virtual void OnValueChanged(EventArgs e) {
			if(ValueChanged != null) ValueChanged.Invoke(this, e);
		}

		#endregion


		#region Method: Rendering hooks

		/// <summary>
		/// Allows a jQuery server control to reference scripts and stylesheets necessary to render their client markup and widgets.
		/// </summary>
		/// <param name="manager">The GreenIsomer.Web.Controls.JQuery.Manager used to handle style and script referencing in addition to unified generation of load and ready scripts.</param>
		protected override void Register(Manager manager) {

			manager.RegisterScriptFile(Settings.Default.CoreScriptFile);
			manager.RegisterScriptFile(Settings.Default.UiCoreScriptFile);
			manager.RegisterScriptFile(Settings.Default.UiSliderScriptFile);

			manager.RegisterStyleFile(Settings.Default.UiCoreStyleFile);
			manager.RegisterStyleFile(Settings.Default.UiSliderStyleFile);
			manager.RegisterThemeStyleFile();

			manager.RegisterControl(this);

			EnsureChildControls();
		}

		/// <summary>
		/// Renders the load script required to generate the client-side jQuery widget.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="script">A GreenIsomer.Web.Controls.JQuery.ScriptBuilder that creates the output stream to render jQuery JavaScript on the client.</param>
		protected override void RenderLoadScript(ScriptBuilder script) {
			script.RenderSelector(ClientID);
			script.Append(".slider(");
			script.RenderProperties(CreateProperties());
			script.Append(");");
		}

		/// <summary>
		/// Creates the properties object that will be rendered as the jQuery UI initialization options.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <returns>A GreenIsomer.Web.Controls.JQuery.Properties object that will become the jQuery UI initialization options.</returns>
		protected override PropertyCollection CreateProperties() {
			PropertyCollection properties = base.CreateProperties();

			bool animate = Animate;
			if(animate != defaultAnimate) properties.AddValue("animate", animate);

			int max = Max;
			if(max != defaultMax) properties.AddValue("max", max);

			int min = Min;
			if(min != defaultMin) properties.AddValue("min", Min);

			Orientation orientation = Orientation;
			if(orientation != defaultOrientation) properties.AddEnumValue("orientation", orientation);

			int step = Step;
			if(step != defaultStep) properties.AddValue("step", step);

			return properties;
		}

		#endregion

	}

}